package nsoft.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.StringTokenizer;

/**
 * @author Laxmi Narayana N
 */
public final class BeanUtilities {

	private BeanUtilities() {
	}

	public static boolean invokeMethod(Object bean, String name, Object[] params) {
		Class[] paramClass;
		paramClass = new Class[params.length];
		int cnt = 0;
		for (Object param : params) {
			paramClass[cnt++] = param.getClass();
		}
		try {
			Method method = getMethod(bean, name, paramClass);
			if(method==null){
				return false;
			}
			getMethod(bean, name, paramClass).invoke(bean, params);
		} catch (Exception e) {
		}
		return true;
	}

	public static Method getMethod(Object bean, String name) {
		try {
			return getMethod(bean, name, new Class[0]);
		} catch (Exception e) {
		}
		return null;
	}

	public static Method getMethod(Object bean, String name, Class[] params) {
		try {
			return bean.getClass().getMethod(name, params);
		} catch (Exception e) {
		}
		return null;
	}

	public static Object getProperty(Object bean, String name) {

		Object value = null;
		String str = name.substring(0, 1).toUpperCase() + name.substring(1);
		Method method;
		// getProperty
		method = getMethod(bean, "get" + str);
		if (method == null) {
			// Boolean Property
			method = getMethod(bean, "is" + str);
		}
		if (method == null) {
			// Simple method.
			method = getMethod(bean, name);
		}
		if (method != null) {
			try {
				// Invoke the method.
				value = method.invoke(bean, new Object[0]);
			} catch (Exception e) {

			}
		}
		return value;
	}

	private static Method getSetterMethod(Class<?> bean, String name,
			Class<?> cls) {
		String str = name.substring(0, 1).toUpperCase() + name.substring(1);
		if (cls != null) {
			Class[] classes = { cls };
			try {
				return bean.getMethod("set" + str, classes);
			} catch (Exception e) {

			}
		} else {
			String methodName = "set" + str;
			for (Method method : bean.getDeclaredMethods()) {
				if (methodName.equalsIgnoreCase(method.getName())) {
					return method;
				}
			}
		}
		return null;
	}

	public static boolean setProperty(Object bean, String name, Object value,
			Class<?> cls) {
		boolean succeess = false;
		Method method;
		try {
			method = getSetterMethod(bean.getClass(), name, cls);
			if (method != null) {
				Object[] objects = { value };
				method.invoke(bean, objects);
				succeess = true;
			}
		} catch (Exception e) {
			succeess = false;
		}
		return succeess;
	}

	public static boolean setProperty(Object bean, String name, Object value) {
		Class<?> cls = null;
		if (value != null) {
			cls = value.getClass();
		}
		return setProperty(bean, name, value, cls);
	}

	public static Class<?> getFieldType(Object bean, String name) {
		if (bean != null) {
			return getSetterMethod(bean.getClass(), name, null)
					.getParameterTypes()[0];
		}
		return null;
	}

	public static Object getPropertyD(Object bean, String property) {

		try {
			if (!property.contains("."))
				return getProperty(bean, property);

			StringTokenizer tokenizer = new StringTokenizer(property, ".");
			Object field = getProperty(bean, tokenizer.nextToken());
			while (tokenizer.hasMoreTokens() && field != null)
				field = getProperty(field, tokenizer.nextToken());
			return field;
		} catch (Exception e) {

		}
		return null;
	}

	public static Field getFiled(Object bean, String property) {
		try {
			if (!property.contains("."))
				return bean.getClass().getDeclaredField(property);

			StringTokenizer tokenizer = new StringTokenizer(property, ".");
			Field field = bean.getClass().getDeclaredField(
					tokenizer.nextToken());
			while (tokenizer.hasMoreTokens() && field != null)
				field = field.getType().getDeclaredField(tokenizer.nextToken());//TODO to check
			return field;
		} catch (Exception e) {

		}
		return null;
	}
}
